/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc. 
 *  
 * SPDX-License-Identifier: Apache-2.0.
 * 
 * @Date: 2021-08-16 17:24:29
 * @LastEditTime: 2021-08-26 10:27:32
 * @Description:  This files is for 
 * 
 * @Modify History: 
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 */
#include <string.h>
#include <stdio.h>
#include "sdkconfig.h"
#ifndef SDK_CONFIG_H__
	#error "Please include sdkconfig.h first"
#endif

#ifndef CONFIG_ENABLE_F_GMAC
	#error "Please include component f_gmac first"
#endif
#include "ft_assert.h"
#include "ft_debug.h"
#include "fsleep.h"
#include "generic_timer.h"
#include "gmac.h"
#include "gmac_hw.h"
#include "lwip/ip4_addr.h"
#include "lwip/init.h"
#include "lwip/timeouts.h"
#include "netif/ethernet.h"
#include "ethernetif.h"

/* board ip addrress */
#define IP_ADDR0        192
#define IP_ADDR1        168 
#define IP_ADDR2        4
#define IP_ADDR3        20 

/* netmask */
#define NETMASK_ADDR0   255
#define NETMASK_ADDR1   255
#define NETMASK_ADDR2   255
#define NETMASK_ADDR3   0

/* gateway */
#define GATEWAY_ADDR0   192
#define GATEWAY_ADDR1   168
#define GATEWAY_ADDR2   4
#define GATEWAY_ADDR3   1

#define SYS_TICKRATE_HZ 100
#define SYS_TICKINTR_PRIORITY  ((0x8 << 4) + 3 * 16)

struct ethernetif {
    struct eth_addr *ethaddr;
    GmacCtrl *ethctrl;
};

static struct netif  netIf;
static ip4_addr_t ipAddr, netMask, gateWay;

#ifdef CONFIG_LWIP_POLL_TEST
void LwipPoll()
{
    u32 cnt = 0;

    printf("enter lwip poll...\r\n");
    while (1)
    {
        /* 调用网卡接收函数 */
        ethernetif_input(&netIf);

        /* 处理LwIP中定时事件 */
        sys_check_timeouts();

        fsleep_millisec(2);
        if (1000 < cnt++)
        {
            cnt = 0;
            printf(".\r\n");
        }
    }
}
#endif

#ifdef CONFIG_LWIP_INTRRUPT_TEST
static boolean dataRecved = FALSE;

void GmacFrameRecvCB(void *param)
{
    FT_ASSERTVOID(param != NULL);
    GmacCtrl *pCtrl = (GmacCtrl *)param;

    printf("dma recv intrrupt\r\n");
    dataRecved = TRUE;

    return;
}

void LwipWaitIntrrupt()
{
    u32 cnt = 0;
    GmacCtrl *pCtrl; /* gmac 控制块 */ 
    struct ethernetif *pNet; /* LWIP helper */   
    struct pbuf *p;

    /* 获取底层驱动控制块 */
    pNet = (struct ethernetif *)netIf.state;
    pCtrl = pNet->ethctrl;

    printf("enter lwip intrrupt waiting...\r\n");    
    while (1)
    {
        while (FALSE == dataRecved) /* 等待中断信号 */
        {
            fsleep_millisec(2);
            if (1000 < cnt++)
            {
                cnt = 0;
                printf(".\r\n");
            }
        }

        /* 调用网卡接收函数 */
        do
        {
            p = low_level_input(&netIf);
            if (NULL != p)
            {
                if (ERR_OK != netIf.input(p, &netIf))
                {
                    pbuf_free(p);
                }
            }
        } while (NULL != p);
        printf("frame recved....\r\n");  
        
        /* 处理LwIP中定时事件 */
        sys_check_timeouts();
        dataRecved = FALSE; 
    }
}
#endif

void LwipRawTest()
{
    memset(&ipAddr, 0, sizeof(ipAddr));
    memset(&netMask, 0, sizeof(netMask));
    memset(&gateWay, 0, sizeof(gateWay));
    memset(&netIf, 0, sizeof(netIf));

    IP4_ADDR(&ipAddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
    IP4_ADDR(&netMask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
    IP4_ADDR(&gateWay, GATEWAY_ADDR0, GATEWAY_ADDR1, GATEWAY_ADDR2, GATEWAY_ADDR3);

    /* 初始化system tick */
    GenericTimerSetupSystick(SYS_TICKRATE_HZ, NULL, SYS_TICKINTR_PRIORITY);

    /* 在没有RTOS的情况下初始化LwIP堆 */
    lwip_init();

    /* 在没有RTOS的情况下添加网络接口 (IPv4/IPv6)  */
    netif_add(&netIf, &ipAddr, &netMask, &gateWay, NULL, ethernetif_init, ethernet_input);

    /* 注册默认网络接口 */
    netif_set_default(&netIf);

    if (netif_is_link_up(&netIf))
    {
        /* 当netif完全配置好时，必须调用该函数 */
        printf("link is up...\r\n");
        netif_set_up(&netIf);
    }
    else
    {
        /* 当netif链接关闭时，必须调用该函数 */
        printf("link is down..\r\n");
        netif_set_down(&netIf);
    }

#ifdef CONFIG_LWIP_POLL_TEST
    LwipPoll();
#endif

#ifdef CONFIG_LWIP_INTRRUPT_TEST
    GmacRegisterEvtHandler(pCtrl, GMAC_RX_COMPLETE_EVT, GmacFrameRecvCB);
    LwipWaitIntrrupt();
#endif
}
